package com.apes.fn.business.fixedLoss.modle;

import com.alibaba.fastjson.annotation.JSONField;
import com.apes.crm.business.model.InsuranceCompany;
import com.apes.fn.business.carAccident.modle.CarAccident;
import com.apes.fn.business.carAccident.repository.CarAccidentRepository;
import com.apes.fn.business.fixedLoss.service.LossQuotationService;
import com.apes.fn.crm.customerExpand.FnCustomerExpand;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.DefaultPersistListener;
import com.apes.framework.jpa.Model;
import com.apes.framework.jpa.comment.Comment;
import com.apes.framework.jpa.generator.ApesGenerator;
import com.apes.framework.plugin.fileserver.File;
import com.apes.framework.plugin.soe.annotations.State;
import com.apes.framework.plugin.soe.annotations.States;
import com.apes.framework.plugin.soe.metadata.BusinessAttributeValue;
import com.apes.framework.util.ApesConst;
import com.apes.framework.util.Arith;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.car.model.CarConfiguration;
import com.apes.scm.masterdata.car.model.CarLabel;
import com.apes.scm.masterdata.car.model.CarModel;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.party.model.PartyRole;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.SelectBeforeUpdate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.persistence.*;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName : LossQuotation
 * @Description : 定损报价单
 * @Author : WSJ
 * @Date: 2020-03-05 16:14
 */
@Getter
@Setter
@SelectBeforeUpdate
@DynamicInsert
@DynamicUpdate
@Entity
@EntityListeners(DefaultPersistListener.class)
@Table(name = LossQuotation.CONST_TABLE_NAME)
public class LossQuotation extends Model {
    public final static String CONST_TABLE_NAME = "ser_loss_quotation";

    @Id
    @Column(name = "id", nullable = false, length = 24)
    @ApesGenerator(code = CONST_TABLE_NAME, name = "定损报价单", padding = 5, prefix = "DS%(company)%(yy)%(month)", useDateRange = true)
    @Comment("定损报价单号")
    private String id;

    @Column(name = "business_type_name", length = 64)
    @Comment("单据类型名称")
    private String businessTypeName = "定损报价";

    @Column(name = "car_Accident",length = 32)
    @Comment("车险报案单")
    private String carAccident;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "fixed_Loss_Dept", referencedColumnName = "id")
    @Comment("定损门店")
    private Dept fixedLossDept;

    /**
     * 查找施工部门
     * @return
     */
    public Dept findWorkDept(){
        return  Objects.equals("B", getOrderType().getCode())?getGetCarDept():getFixedLossDept();
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "assist_Base", referencedColumnName = "id")
    @Comment("协助定损基地")
    private Dept assistBase;

    @Transient
    private String assistBaseID;

    public String getAssistBaseID() {
        if (assistBase == null ) {
            return null;
        }
        return assistBase.getBranch().getId();
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "get_Car_Dept", referencedColumnName = "id")
    @Comment("接车门店")
    private Dept getCarDept;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "company_id", referencedColumnName = "id", nullable = false)
    @Comment("所属公司")
    private PartyRole company;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "loss_Officer", referencedColumnName = "id", nullable = false)
    @Comment("定损员")
    private PartyRole lossOfficer;


    @States(name = "申请审核事项", values = {
            @State(id = "A", name = "价格申请"),
            @State(id = "B", name = "要货申请"),
            @State(id = "C", name = "提前修车申请")
    })
    @Comment("申请审核事项")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "apply_Approve", referencedColumnName = "id")
    private BusinessAttributeValue applyApprove;

    @States(name = "单据状态", values = {
            @State(id = "create", name = "新增"),
            @State(id = "toTechAudit", name = "转技术审核"),
            @State(id = "techAudit", name = "技术审核"),
            @State(id = "toBusinessAudit", name = "转商务审核"),
            @State(id = "businessAudit", name = "商务审核"),
            @State(id = "toInquiry", name = "转询价"),
            @State(id = "inquiryFinish", name = "询价完成"),
            @State(id = "confirmPlan", name = "定损已出单"),
            @State(id = "dividendApprove", name = "分成待审核"),
            @State(id = "goBack", name = "退回"),
            @State(id = "appendApply", name = "追加申请"),
            @State(id = "applyHelp", name = "申请协助"),
            @State(id = "repeal", name = "终止"),
            @State(id = "turnRequireProduct", name = "要货待审核"),
            @State(id = "turnRepairApprove", name = "修车待审核"),
            @State(id = "suspend", name = "定损暂停"),
    })
    @Column(name = "state", length = 32, nullable = false)
    @Comment("单据状态")
    private String state = "create";

    public String getReceivedState() {
        if (receivedState==null)return "none";
        return receivedState;
    }

    @States(name = "单据状态", values = {
            @State(id = "none", name = "未到账"),
            @State(id = "portion", name = "部分到账"),
            @State(id = "all", name = "全部到账"),
    })
    @Column(name = "received_state")
    @Comment("到账状态")
    private String receivedState = "none";

    public void setLossReceivedItem(List<LossReceivedItem> lossReceivedItem){
        if (lossReceivedItem == null) {
            this.lossReceivedItem = new ArrayList<>();
            return;
        }
        this.lossReceivedItem = lossReceivedItem;
    }

    @OneToMany(mappedBy = "lossQuotation", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<LossReceivedItem> lossReceivedItem = new ArrayList();

    public List<LossReceivedItem> getLossReceivedItem() {
        if(lossReceivedItem.size() == 0) {
            return lossReceivedItem;
        }
        for (LossReceivedItem item : lossReceivedItem) {

            item.setLossQuotation(this);
        }
        return lossReceivedItem;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "to_Business_uid", referencedColumnName = "id")
    @Comment("转商务审核人")
    private PartyRole toBusinessUid;

    @JSONField(format = DateUtil.SHOW_DATETIME_FORMAT)
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "to_Business_Date")
    @Comment("转商务审核日期")
    private Date toBusinessDate;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "approve_uid", referencedColumnName = "id")
    @Comment("商务审核人")
    private PartyRole approveUid; //审批人

    @JSONField(format = DateUtil.SHOW_DATETIME_FORMAT)
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "approve_Date")
    @Comment("商务审核日期")
    private Date approveDate; //审批日期

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "to_Tech_Uid", referencedColumnName = "id")
    @Comment("转技术审核人")
    private PartyRole toTechUid;

    @JSONField(format = DateUtil.SHOW_DATETIME_FORMAT)
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "to_Tech_Date")
    @Comment("转技术审核时间")
    private Date toTechDate;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "teach_Uid", referencedColumnName = "id")
    @Comment("技术审核人")
    private PartyRole teachUid;

    @JSONField(format = DateUtil.SHOW_DATETIME_FORMAT)
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "tech_Date")
    @Comment("技术审核时间")
    private Date techDate;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "inquiry_Uid", referencedColumnName = "id")
    @Comment("转询价人")
    private PartyRole inquiryUid;

    @JSONField(format = DateUtil.SHOW_DATETIME_FORMAT)
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "inquiry_Date")
    @Comment("转询价日期")
    private Date inquiryDate;

    @JSONField(format = DateUtil.SHOW_DATETIME_FORMAT)
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "receivable_date")
    @Comment("收款日期")
    private Date receivableDate;

    @JSONField(format = DateUtil.SHOW_DATETIME_FORMAT)
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "post_date")
    @Comment("记账日期")
    private Date postDate;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "confirm_Uid", referencedColumnName = "id")
    @Comment("确认方案人")
    private PartyRole confirmUid;

    @JSONField(format = DateUtil.SHOW_DATETIME_FORMAT)
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "confirm_Date")
    @Comment("确认方案时间")
    private Date confirmDate;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "repeal_uid", referencedColumnName = "id")
    @Comment("终止人")
    private PartyRole repealUid;

    @JSONField(format = DateUtil.SHOW_DATETIME_FORMAT)
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "repeal_date")
    @Comment("终止日期")
    private Date repealDate;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "back_Uid", referencedColumnName = "id")
    @Comment("退回人")
    private PartyRole backUid;

    @JSONField(format = DateUtil.SHOW_DATETIME_FORMAT)
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "back_Date")
    @Comment("退回日期")
    private Date backDate;

    @Column(name = "tech_Audit_Remarks", length = 256)
    @Comment("技术审核备注")
    private String techAuditRemarks;

    @Column(name = "business_Remarks", length = 256)
    @Comment("商务备注")
    private String businessRemarks;

    @Column(name = "remark", length = 256)
    @Comment("备注")
    private String remark;

    @JSONField(format = DateUtil.SHOW_DATETIME_FORMAT)
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "fixed_Loss_Date")
    @Comment("保险公司定损时间")
    private Date fixedLossDate;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "insurance_company_id", referencedColumnName = "id")
    @Comment("保险公司")
    private InsuranceCompany insuranceCompany;

    @Column(name = "fixed_loss",columnDefinition = ApesConst.FIELD_BOOLEAN_FALSE)
    @Comment("定损标记")
    private boolean fixedLoss = false;

    @Comment("水泡车")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "waterloggedCar", referencedColumnName = "id")
    private Enumeration waterloggedCar;

    @Column(name = "discount_Payment",columnDefinition = ApesConst.FIELD_BOOLEAN_FALSE)
    @Comment("折扣赔付")
    private boolean discountPayment = false;

    @Column(name = "third_Party", length = 256)
    @Comment("第三方")
    private String thirdParty;

    @States(name = "订单类型", values = {
            @State(id = "A", name = "卖单模式"),
            @State(id = "B", name = "委托定损")
    })
    @Comment("订单类型")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "order_Type",  referencedColumnName = "id")
    private BusinessAttributeValue orderType;

    @Comment("案件类型")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "case_type", referencedColumnName = "id")
    private Enumeration caseType;

    @Column(name = "return_Ratio", columnDefinition = ApesConst.FIELD_16_4_0)
    @Comment("正常返还率")
    private double returnRatio = 0;

    @Column(name = "service_Return_Ratio", columnDefinition = ApesConst.FIELD_16_4_0)
    @Comment("工时追加返还率")
    private double serviceReturnRatio = 0;

    @Column(name = "return_Ratio_Accessories", columnDefinition = ApesConst.FIELD_16_4_0)
    @Comment("配件追加返还率")
    private double returnRatioAccessories = 0;

    @Column(name = "dividend_Store", columnDefinition = ApesConst.FIELD_16_4_0)
    @Comment("门店分红率")
    private double dividendStore = 0;

    @Column(name = "dividendPlat_form", columnDefinition = ApesConst.FIELD_16_4_0)
    @Comment("平台分红率")
    private double dividendPlatform = 0;

    @Column(name = "dividend_Base", columnDefinition = ApesConst.FIELD_16_4_0)
    @Comment("基地分红率")
    private double dividendBase = 0;

    @Column(name = "pick_Car_Profit", columnDefinition = ApesConst.FIELD_16_4_0)
    @Comment("接车门店毛利率")
    private double pickCarProfit = 0;

    @Column(name = "fixedLoss_Profit", columnDefinition = ApesConst.FIELD_16_4_0)
    @Comment("定损门店毛利率")
    private double fixedLossProfit = 0;



    @Column(name = "adjust_amount", columnDefinition = ApesConst.FIELD_16_4_0)
    @Comment("调整金额")
    private double adjustAmount = 0;

    @Column(name ="risk_Car", columnDefinition = ApesConst.FIELD_BOOLEAN_FALSE)
    @Comment("定损风险车")
    private boolean riskCar = false;



    @Comment("会员扩展信息")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "customer_expand_id", referencedColumnName = "id")
    private FnCustomerExpand customerExpand;

    @Column(name = "out_system_business", columnDefinition = "number(1,0)")
    @Comment("体系外合作单位业务")
    private boolean outSystemBusiness = false;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "car_configuration_id", referencedColumnName = "id")
    @Comment("车型配置")
    private CarConfiguration carConfiguration;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "car_model_id", referencedColumnName = "id")
    @Comment("车型")
    private CarModel carModel;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "car_label_id", referencedColumnName = "id")
    @Comment("厂牌")
    private CarLabel carLabel;

    @OneToMany(mappedBy = "lossQuotation", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<PickCarTypeBusiness> typeBusinesses = new ArrayList();

    public List<PickCarTypeBusiness> getTypeBusinesses() {
        if(typeBusinesses.size() == 0) {
            return new  ArrayList();
        }
        for (PickCarTypeBusiness item : typeBusinesses) {
            // if("T1".equals(item.getPickUpType().getId()) && (item.getRemarks() == null || "".equals(item.getRemarks().trim()))){
            //     throw new RuntimeException("接车类型为其他，必须填写备注信息");
            // }
            item.setLossQuotation(this);
        }
        return typeBusinesses;
    }

    @Column(name = "get_Car_Type", length = 256)
    @Comment("接车类型")
    private String getCarType;

    public void setTypeBusinesses(List<PickCarTypeBusiness> pickCarTypeBusinesses){
        this.typeBusinesses.clear();
        if (pickUpType != null && pickUpType.size() > 0) {
            List<PickCarTypeBusiness> list = pickUpType.stream().map(
                    item -> {
                        PickCarTypeBusiness carTypeBusiness = new PickCarTypeBusiness();
                        carTypeBusiness.setPickUpType(item);
                        carTypeBusiness.setLossQuotation(this);
                        return carTypeBusiness;
                    }
            ).collect(Collectors.toList());
            this.typeBusinesses.addAll(list);
        }
    }

    @Transient
    private List<Enumeration> pickUpType= new ArrayList();
    public List<Enumeration> getPickUpType() {
        if(typeBusinesses == null) return new  ArrayList();
        return  typeBusinesses.stream().map(PickCarTypeBusiness::getPickUpType).collect(Collectors.toList());
    }



    @States(name = "理赔类型", values = {
            @State(id = "A", name = "快赔"),
            @State(id = "B", name = "全部直赔"),
            @State(id = "C", name = "传统理赔"),
            @State(id = "D", name = "部分直赔")
    })
    @Comment("理赔类型")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "claim_Type",  referencedColumnName = "id")
    private BusinessAttributeValue claimType;

    @Transient
    private Map customer;

    public Map getCustomer() {
        if (customerExpand == null || customerExpand.getMobile() == null){
            return null;
        }
        return MapUtil.mapper(
                "realname", customerExpand.getRealname(),
                "mobile", customerExpand.getMobile(),
                "level", customerExpand.getCustomerLevelId(),
                "vendorCode", customerExpand.getVendorCode(),
                "userRole", MapUtil.mapper(
                        "id", customerExpand.getUserRoleId(),
                        "name", customerExpand.getUserRoleName()
                )
        );
    }

    @File
    @Lob
    @Comment("事故照片")
    @Basic(fetch = FetchType.LAZY)
    @Column(name = "accident_Photos", columnDefinition = "CLOB")
    private String accidentPhotos;

    @Transient
    private Map customerCar;

    @Transient
    private String suspendReason;

    public Map getCustomerCar() {
        if (customerExpand == null || customerExpand.getCarLicense() == null) return null;
        return MapUtil.mapper(
                "carLicense", customerExpand.getCarLicense(),
                "vendorCode", customerExpand.getVendorCode(),
                "customer", this.getCustomer(),
                "vin",customerExpand.getVin(),
                "carServiceLevel", StringUtils.isEmpty(customerExpand.getCarModelService())? "": "["+customerExpand.getCarModelService()+"]",
                "jekunModelCode",customerExpand.getJekunModelCode()
        );
    }
    @Transient
    private Map fnCustomerExpandTemp;
    public Map getFnCustomerExpandTemp(){
        if(this.customerExpand != null) return MapUtil.mapped(this.customerExpand);
        return null;
    }
    /**
     明细
     */
    @OneToMany(mappedBy = "lossQuotation", cascade = CascadeType.ALL, orphanRemoval = true)
    @OrderBy("product,evaluationType")
    private List<LossQuotationItem> lossQuotationItems = new ArrayList<>();

    public List<LossQuotationItem> getLossQuotationItems() {
        if (lossQuotationItems == null) lossQuotationItems = new ArrayList<>();
        for (LossQuotationItem item : lossQuotationItems) {
            item.setLossQuotation(this);
        }

        lossQuotationItems.sort(Comparator.comparing(item -> item.getProduct().getId()));
        lossQuotationItems.sort(Comparator.comparing(item -> item.getEvaluationType().getId()));
        return lossQuotationItems;
    }
    /**
     确认方案
     */
    @OneToMany(mappedBy = "lossQuotation", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<LossQuotationPlan> lossQuotationPlans = new ArrayList<>();


    public List<LossQuotationPlan> getLossQuotationPlans() {
        if (lossQuotationPlans == null ){
            return new ArrayList<>();
        }
        for (LossQuotationPlan item : lossQuotationPlans) {
            item.setLossQuotation(this);
        }
        return lossQuotationPlans;
    }

    public void setLossQuotationPlans (List<LossQuotationPlan> lossQuotationPlans) {
        this.lossQuotationPlans.clear();
        if (lossQuotationPlans != null) {
            this.lossQuotationPlans.addAll(lossQuotationPlans);
        }
    }
    @OneToMany(mappedBy = "lossQuotation",cascade = CascadeType.ALL, orphanRemoval = true)
    private  List<LossQuotationRecord> lossQuotationRecords = new ArrayList<>();

    public List<LossQuotationRecord> getLossQuotationRecords() {
        if (lossQuotationRecords == null ) {
            return new ArrayList<>();
        }
        for (LossQuotationRecord item : lossQuotationRecords) {
            item.setLossQuotation(this);
        }
        return lossQuotationRecords;
    }

    public void setLossQuotationRecords(List<LossQuotationRecord> lossQuotationRecords) {
        this.lossQuotationRecords.clear();
        if (lossQuotationRecords != null) {
            this.lossQuotationRecords.addAll(lossQuotationRecords);
        }
    }

    @Column(name = "profit", columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("毛利率")
    private double profit = 0;
    @Column(name = "price_Difference", columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("差价合计")
    private double priceDifference = 0;



    @Column(name = "insurance_Offer", columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("保险公司报价合计")
    private double insuranceOffer = 0;

    @Column(name = "sales_Amount", columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("内部报价合计")
    private double salesAmount = 0;

    @Column(name = "refer_Tax", columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("成本金额合计")
    private double referTax = 0;


    /**
     * 更新到账状态
     * -检查是否完成分摊/未完成自动分摊
     * -到账金额为零等于未到账
     * -到账金额不可小于零
     * -到账金额大于等于定损金额则全部到账 否则部分到账
     * -如果有调整金额则跟调整金额比较
     */
    public void updateReceivedState(){
        double receivedAmount = getReceivedAmount();
        checkApportion(this);
        if (receivedAmount==0){
            this.receivedState = "none";
            return;
        }
        if (receivedAmount<0)throw new RuntimeException("总到账金额不可小于零");

        double insuranceOffer = this.adjustAmount+this.insuranceOffer;
//        if (receivedAmount>insuranceOffer)throw new RuntimeException("总到账金额不可大于实定损金额");
        if (receivedAmount>= insuranceOffer){
            this.receivedState = "all";
        }else {
            this.receivedState = "portion";
        }
    }


    private void checkApportion(LossQuotation lossQuotation) {
        //开始分摊
        SpringManager.getBean(LossQuotationService.class).completeApportion(lossQuotation);
        //定损调整金额回写
        SpringManager.getBean(LossQuotationService.class).writeAdjustmentAmount(lossQuotation);;
    }

    @Transient
    private Double receivedAmount;//到账金额

    public Double getReceivedAmount() {
        receivedAmount = getLossReceivedItem().stream().mapToDouble(LossReceivedItem::getReceivedAmount).sum();
        return receivedAmount;
    }
    /**
     * 计算定损明细上的各个金额合计
     */
    public void computeAmount(){
        if(this.lossQuotationItems!=null&&!this.lossQuotationItems.isEmpty()){
            this.referTax = 0;
            this.salesAmount = 0;
            for (LossQuotationItem lossQuotationItem : this.lossQuotationItems) {
                this.referTax +=lossQuotationItem.getReferTax();
                this.salesAmount +=lossQuotationItem.getSalesAmount();
            }
        }
        if(this.lossQuotationPlans != null&&!this.lossQuotationPlans.isEmpty()) {
            this.priceDifference = 0;
            this.insuranceOffer = 0;
            this.profit = 0;
            this.pickCarProfit = 0;
            this.fixedLossProfit = 0;
            double referTax = 0;
            for(LossQuotationPlan lossQuotationPlan : this.lossQuotationPlans){
                this.insuranceOffer += lossQuotationPlan.getFixedLossAmount();
                this.priceDifference += lossQuotationPlan.getPriceDifference();
                referTax+=lossQuotationPlan.getReferTax();
            }
            this.insuranceOffer = Arith.round(this.insuranceOffer,2);
            this.priceDifference = Arith.round(this.priceDifference,2);
            this.profit = Arith.sub( this.insuranceOffer,referTax);
            if (this.insuranceOffer==0)throw new RuntimeException("保险公司金额不能为零");
            this.profit = Arith.div( this.profit,this.insuranceOffer,4);
            this.profit = Arith.round(this.profit * 100, 2);
            double pickCarProfit = (this.insuranceOffer - referTax - this.insuranceOffer * this.dividendBase - this.insuranceOffer * this.dividendPlatform) / this.insuranceOffer;
            double fixedLossProfit = 0;
            if (orderType.getCode().equals("A")){
                if (this.getCarDept.getId().equals(this.fixedLossDept.getId())){
                    fixedLossProfit = (this.insuranceOffer - referTax - this.insuranceOffer * this.dividendStore - this.insuranceOffer * this.dividendPlatform) / this.insuranceOffer;
                    pickCarProfit = 0;
                }else {
                    pickCarProfit = 1;
                    fixedLossProfit = (this.insuranceOffer - referTax - this.insuranceOffer * this.dividendStore - this.insuranceOffer * this.dividendPlatform) / this.insuranceOffer;
                }
            }else {
                fixedLossProfit=1;
            }
            this.pickCarProfit = Arith.round(pickCarProfit * 100, 2);
            this.fixedLossProfit = Arith.round(fixedLossProfit * 100, 2);

        }
    }

    @Transient
    @Comment("定损金额")
    private double totalAmount;

    public double getTotalAmount() {
        if (insuranceOffer <= 0) return totalAmount;
        return insuranceOffer;
    }

    @Transient
    @Comment("已填写金额")
    private String writerAmount;

    public String getWriterAmount(){
        double plansTotalAmount = 0.0;  // 确认方案金额总价
        double differenceAmount = 0.0;  // 确认方案金额与总金额差异
        List<LossQuotationPlan> lossQuotationPlans = getLossQuotationPlans();
        for (LossQuotationPlan lossQuotationPlan : lossQuotationPlans) {
            double fixedLossAmount = lossQuotationPlan.getFixedLossAmount();
            plansTotalAmount = Arith.round(Arith.add(plansTotalAmount,fixedLossAmount),2);
        }
        differenceAmount = Arith.round(Arith.sub(plansTotalAmount,getTotalAmount()),2);
        return plansTotalAmount + "(总金额)  " +  differenceAmount + "(差异)";
    }


    public boolean checkAmount () {
        return  insuranceOffer == totalAmount;
    }

    public CarAccident queryCarAccident () {
        if (StringUtils.isEmpty(this.carAccident)) throw new RuntimeException("定损报价单中的车险报案号不存在");
        return SpringManager.getBean(CarAccidentRepository.class).findOne(this.carAccident);
    }

    //计算自费金额(税收比率为13)
    public double computePayYourselfForThirteen() {
        if (this.lossQuotationPlans ==null) return 0;
        return this.lossQuotationPlans.stream()
                .filter(
                        item -> item.isPayYourself() &&  item.getProduct().getTax().getAmt() ==13
                )
                .mapToDouble(LossQuotationPlan::getFixedLossAmount).sum();

    }

    //计算自费金额(税收比率为6)
    public double computePayYourselfForSix() {
        if (this.lossQuotationPlans ==null) return 0;
        return this.lossQuotationPlans.stream()
                .filter(
                        item -> item.isPayYourself() &&  item.getProduct().getTax().getAmt() ==6
                )
                .mapToDouble(LossQuotationPlan::getFixedLossAmount).sum();

    }

    @Transient
    private boolean needBusinessAudit = true;

    public boolean getNeedBusinessAudit() {
        if (Objects.isNull(applyApprove)){
            return  false;
        }
        //如果是委托定损 则都需要门店审核
        if (Objects.nonNull(orderType) && Objects.equals("B", orderType.getCode())) {
            return true;
        }
        String applyType = this.getApplyApprove().getName();
        switch (applyType) {
            case "提前修车申请":
                return false;
            case "要货申请":
                return judgmentRequireGoodsAudit();
            case "价格申请" :
                return judgmentWhetherAudit();
            default:
                throw new RuntimeException("未知的申请审核类型:" + applyType);
        }
    }

    @Transient
    private int companyType;
    /**
     companyType 公司性质 0: 直营, 1:合伙人 ,2:赋能,3:直营子公司
     */
    public int getCompanyType() {
        //如果是委托定损,则直接默认是赋能
        if (Objects.nonNull(orderType) && Objects.equals("B", orderType.getCode())) {
            return 2;
        }
        String name = this.fixedLossDept.getCompany().getParty().getCorporate().getOperation().getCode();
        switch (name) {
            case "0":
            case "1":
            case "2":
                return Integer.parseInt(name);
            case "3":
                return 0;
            default:
                throw new RuntimeException("运营模式不是数字类型的编码!!!");
        }
    }

    /**
     * 判断是否需要商务审核
     * @return
     */
    public boolean judgmentWhetherAudit () {
		/*  该单据的毛利率不大于45%
			a、定损报价单页签，“确认方案”含原厂件配件商品，需要商务审核。
			b、同一个钣金喷漆商品，数量>1，需要商务审核。
			c、单个配件商品，毛率为负数时，需要商务审核。
			d、单个配件商品，毛率为负数时，且整单毛率>45%时，需要商务审核。
		 */
        if (this.getProfit() <=45 ){
            return true;
        }
        List<LossQuotationPlan> list = this.getLossQuotationPlans().stream().filter(
                item -> item.getProfit() <0
                        || ( Objects.nonNull(item.getProduct().getBrand().getQuality()) &&
                        Objects.equals("000003",item.getProduct().getBrand().getQuality().getCode()))
                        || (Objects.equals("007",item.getServeType().getId()) && item.getSaleQty() > 1)

        ).collect(Collectors.toList());
        return  list.size() >0;
    }

    /**
     * 获取定损配件和工时总金额
     */
    public Map gotLossQuotationRelated () {
        Map<String, Object> map = new HashMap<>(10);
        boolean flag = (this.getServiceReturnRatio() > 0 || this.getReturnRatioAccessories() > 0);
        double serviceAmount = this.getLossQuotationPlans().stream()
                .filter(item -> Objects.equals("20", item.getProduct().getProductGroup().getId()))
                .mapToDouble(LossQuotationPlan::getFixedLossAmount).sum();

        double accessoriesAmount = this.getLossQuotationPlans().stream()
                .filter(item ->  Objects.equals("10", item.getProduct().getProductGroup().getId()))
                .mapToDouble(LossQuotationPlan::getFixedLossAmount).sum();

        map.put("flag", flag);
        map.put("serviceAmount", serviceAmount);
        map.put("accessoriesAmount", accessoriesAmount);
        return map;
    }

    /**
     * 判断要货是否需要审核
     */
    public boolean judgmentRequireGoodsAudit () {
        List<LossQuotationItem> list = this.lossQuotationItems.stream().filter(
                item-> item.getRequireQty() > 0
        ).collect(Collectors.toList());
        //如果明细商品品质为空则需要审核
        if (list.size() == 0) {
            return false;
        }
        for(LossQuotationItem item:list) {
            if (Objects.isNull(item.getProduct().getBrand().getQuality())){
                return true;
            }
        }
        // 000001 品牌件 ; 000002 名牌件 ; 000003 原厂件 ; 000004 下线件
        String brandParts = "000001";
        String imitateParts = "000002";
        String originalParts = "000003";
        //如果要货商品全是品牌件和名牌件, 不需要商务审核
        boolean flag = list.stream().allMatch(
                item -> Objects.equals(brandParts, item.getProduct().getBrand().getQuality().getCode())
                        || Objects.equals(imitateParts, item.getProduct().getBrand().getQuality().getCode())
        );
        if (flag) {
            return false;
        }else {
            //如果要货商品全是品牌件,名牌件和原厂件,并原厂件的最低限价<= 150  , 不需要商务审核
            boolean flagTow = list.stream().allMatch(
                    item ->
                            Objects.equals(brandParts, item.getProduct().getBrand().getQuality().getCode())
                                    || Objects.equals(imitateParts, item.getProduct().getBrand().getQuality().getCode())
                                    || Objects.equals(originalParts, item.getProduct().getBrand().getQuality().getCode())

            );
            if (flagTow) {
                return list.stream().filter(
                        item -> Objects.equals(originalParts, item.getProduct().getBrand().getQuality().getCode())
                ).anyMatch(
                        item -> item.getReferTax() > 150
                );
            }else{
                return true;
            }
        }
    }

    @Transient
    private String fixedLossDeptId;

    public String getFixedLossDeptId() {
        if (Objects.nonNull(orderType) && Objects.equals("B", orderType.getCode())) {
            if (getCarDept == null) {
                return null;
            }
            return getCarDept.getBranch().getId();
        } else {
            if (fixedLossDept == null) {
                return null;
            }
            return fixedLossDept.getBranch().getId();
        }
    }
    @Transient
    private String orderTypeTemp ="定损报价单";//用于前端判断方案类型,并且是否有询价标记
    @Transient
    private String orderType2 = "自定损";//固定类型

    @Transient
    private List<String> errorMsg;
    public void addErrorMsg(String msg){
        this.errorMsg = this.errorMsg==null?this.errorMsg=new ArrayList<String>(): this.errorMsg;
        this.errorMsg.add(msg);
        this.errorMsg = this.errorMsg.stream().distinct().collect(Collectors.toList());
    }
}
